﻿using Dm;
using Microsoft.AspNetCore.Mvc;

namespace RuoVea.Swms.Server.Service
{
    /// <summary>
    /// 存放位置管理
    /// </summary>
    [ApiExplorerSettings(GroupName = "swms")]
    public class LocationService : IApplicationService
    {
        private readonly SugarRepository<WmsProduct> _productRepo;
        private readonly SugarRepository<WmsLocation> _locationRepo;
        private readonly ICurrentUser _currentUser;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="productRepo"></param>
        /// <param name="stockInRepo"></param>
        /// <param name="stockOutRepo"></param>
        /// <param name="historyRepo"></param>
        /// <param name="categoryRepo"></param>
        /// <param name="locationRepo"></param>
        /// <param name="currentUser"></param>
        public LocationService(
            SugarRepository<WmsProduct> productRepo,
            SugarRepository<WmsLocation> locationRepo,
            ICurrentUser currentUser)
        {
            _productRepo = productRepo;
            _locationRepo = locationRepo;
            _currentUser = currentUser;
        }

        /// <summary>
        /// 获取位置分页列表
        /// </summary>
        public async Task<RestfulResult<PageResult<WmsLocation>>> GetPagesAsync(LocationPageParam data)
        {
            var restful = new RestfulResult<PageResult<WmsLocation>> { Code = CodeStatus.OK };
            data ??= new LocationPageParam { PageNo = 1, PageSize = 10 };

            var query = await _locationRepo.AsQueryable()
                .WhereIF(!string.IsNullOrEmpty(data.Area), u => u.Area.Contains(data.Area))
                .WhereIF(!string.IsNullOrEmpty(data.Keyword),
                    u => u.Name.Contains(data.Keyword) || u.Code.Contains(data.Keyword))
                .ToPageAsync(data.PageNo, data.PageSize);

            restful.Data = query;
            return restful;
        }
 
        /// <summary>
        /// 获取所有位置列表（用于下拉选择）
        /// </summary>
        public async Task<RestfulResult<List<WmsLocation>>> GetlistAsync()
        {
            var restful = new RestfulResult<List<WmsLocation>> { Code = CodeStatus.OK };
            var locations = await _locationRepo.GetListAsync();
            restful.Data = locations;
            return restful;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task<RestfulResult<List<string>>> GetLocationAreasAsync()
        {
            var restful = new RestfulResult<List<string>> { Code = CodeStatus.OK };
            var areas = await _locationRepo.AsQueryable()
                .GroupBy(u => u.Area)
                .Select(u => u.Area)
                .ToListAsync();
            restful.Data = areas;
            return restful;
        }
        /// <summary>
        /// 添加存放位置
        /// </summary>
        [UnitOfWork]
        public async Task<RestfulResult> AddAsync(WmsLocation data)
        {
            var restful = new RestfulResult { Code = CodeStatus.BadRequest };

            // 验证编码唯一性
            var exists = await _locationRepo.IsAnyAsync(u => u.Code == data.Code);
            if (exists)
            {
                restful.Message = "位置编码已存在";
                return restful;
            }

            // 验证容量
            if (data.MaxCapacity.HasValue && data.MaxCapacity <= 0)
            {
                restful.Message = "最大容量必须大于0";
                return restful;
            }

            data.Creator = _currentUser.UserId;
            data.CurrentCapacity = 0;
            bool result = await _locationRepo.InsertAsync(data);
            restful.Data = result;
            restful.Code = result ? CodeStatus.OK : CodeStatus.BadRequest;
            restful.Message = result ? "添加成功" : "添加失败";
            return restful;
        }

        /// <summary>
        /// 更新存放位置
        /// </summary>
        public async Task<RestfulResult> UpdateAsync(WmsLocation data)
        {
            var restful = new RestfulResult { Code = CodeStatus.BadRequest };

            // 验证位置是否存在
            var exists = await _locationRepo.IsAnyAsync(u => u.Id == data.Id);
            if (!exists)
            {
                restful.Message = "位置不存在";
                return restful;
            }

            // 验证容量
            if (data.MaxCapacity.HasValue)
            {
                var current = await _locationRepo.GetByIdAsync(data.Id);
                if (data.MaxCapacity < current.CurrentCapacity)
                {
                    restful.Message = $"最大容量不能小于当前容量({current.CurrentCapacity})";
                    return restful;
                }
            }
            WmsLocation storageLocation = new()
            {
                Id=data.Id,
                Name = data.Name,
                Area = data.Area,
                Shelf = data.Shelf,
                MaxCapacity = data.MaxCapacity,
                Remark = data.Remark
            };
            bool result = await _locationRepo.UpdateAsync(storageLocation);
            restful.Data = result;
            restful.Code = result ? CodeStatus.OK : CodeStatus.BadRequest;
            restful.Message = result ? "更新成功" : "更新失败";
            return restful;
        }

        /// <summary>
        /// 删除存放位置
        /// </summary>
        public async Task<RestfulResult> DeleteAsync([FromBody] EntityBaseId data)
        {
            var restful = new RestfulResult { Code = CodeStatus.BadRequest };

            // 检查是否有产品使用此位置
            var hasProducts = await _productRepo.IsAnyAsync(u => u.LocationId == data.Id);
            if (hasProducts)
            {
                restful.Message = "有产品使用此位置，无法删除";
                return restful;
            }

            bool result = await _locationRepo.DeleteByIdAsync(data.Id);
            restful.Data = result;
            restful.Code = result ? CodeStatus.OK : CodeStatus.BadRequest;
            restful.Message = result ? "删除成功" : "删除失败";
            return restful;
        }

        /// <summary>
        /// 更新位置当前容量（线程安全方式）
        /// </summary>
        /// <param name="locationId">位置ID</param>
        /// <param name="quantityChange">数量变化（正数表示增加，负数表示减少）</param>
        /// <returns>返回更新是否成功</returns>
        public async Task<bool> UpdateLocationCapacity(long locationId, int quantityChange)
        {
            if (quantityChange == 0) return true;

            // 使用数据库乐观锁确保并发安全
            var location = await _locationRepo.GetByIdAsync(locationId);

            if (location == null) return false;

            // 计算新容量
            int newCapacity = (location.CurrentCapacity??0) + quantityChange;

            // 验证容量
            if (newCapacity < 0)
                throw new InvalidOperationException($"位置容量不足，无法减少 {quantityChange} (当前: {location.CurrentCapacity})");

            if (location.MaxCapacity.HasValue && newCapacity > location.MaxCapacity.Value)
                throw new InvalidOperationException($"超出位置最大容量 {location.MaxCapacity} (尝试设置为: {newCapacity})");

            //var result = await _locationRepo.UpdateAsync(
            //    u => u.Id == locationId && u.CurrentCapacity == location.CurrentCapacity,
            //    u => new StorageLocation { CurrentCapacity = newCapacity });

            // 使用条件更新确保数据一致性
            var result = await _locationRepo.AsUpdateable( new WmsLocation { CurrentCapacity = newCapacity }).Where(
                u => u.Id == locationId && u.CurrentCapacity == location.CurrentCapacity
                ).IgnoreNullColumns().ExecuteCommandAsync()>0;

            if (!result)
            {
                // 如果更新失败，可能是并发冲突，可以重试或抛出异常
                throw new Exception("位置容量更新失败，可能已被其他操作修改");
            }

            return true;
        }
    }
}